# 此文件保留但不再使用，项目已移除Redis缓存
# 如需使用缓存，请使用Django默认的缓存API
"""
from django.core.cache import cache

# 使用示例
cache.set('key', 'value', timeout=60)  # 设置缓存，60秒过期
value = cache.get('key')  # 获取缓存
cache.delete('key')  # 删除缓存
"""

from django.core.cache import caches
from django.conf import settings
from functools import wraps
import hashlib
import time

# 获取不同类型的缓存
product_cache = caches['product_cache']
# 使用默认缓存代替page_cache
default_cache = cache  # 使用默认缓存

def generate_cache_key(prefix, *args, **kwargs):
    """
    生成缓存键，基于参数和关键字参数
    
    Args:
        prefix: 缓存键前缀
        *args: 位置参数
        **kwargs: 关键字参数
        
    Returns:
        str: 生成的缓存键
    """
    # 将所有参数转换为字符串
    key_parts = [str(arg) for arg in args]
    key_parts.extend([f"{k}={v}" for k, v in sorted(kwargs.items())])
    
    # 使用MD5生成固定长度的键
    if key_parts:
        key_str = "_".join(key_parts)
        hashed = hashlib.md5(key_str.encode()).hexdigest()
        return f"{prefix}_{hashed}"
    
    return prefix

def cache_result(prefix, timeout=3600, cache_alias='default'):
    """
    函数结果缓存装饰器
    
    Args:
        prefix: 缓存键前缀
        timeout: 缓存超时时间（秒）
        cache_alias: 使用的缓存别名
        
    Returns:
        function: 装饰器函数
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存键
            cache_key = generate_cache_key(prefix, *args, **kwargs)
            
            # 获取缓存
            selected_cache = caches[cache_alias]
            result = selected_cache.get(cache_key)
            
            # 如果缓存不存在，则执行函数并缓存结果
            if result is None:
                result = func(*args, **kwargs)
                selected_cache.set(cache_key, result, timeout)
            
            return result
        return wrapper
    return decorator

def clear_cache_by_pattern(pattern, cache_alias='default'):
    """
    清除匹配模式的缓存（仅适用于本地开发环境测试）
    注意：这不是生产环境的推荐做法，因为它遍历所有键
    
    Args:
        pattern: 缓存键模式（前缀）
        cache_alias: 使用的缓存别名
    """
    selected_cache = caches[cache_alias]
    
    # 获取Redis连接
    if hasattr(selected_cache, 'client') and hasattr(selected_cache.client, 'get_client'):
        client = selected_cache.client.get_client()
        pattern_with_prefix = f"{selected_cache.key_prefix}:{pattern}*"
        
        # 使用scan_iter避免阻塞Redis
        keys = client.scan_iter(match=pattern_with_prefix)
        for key in keys:
            client.delete(key)

def invalidate_product_cache(product_id):
    """
    使特定产品的缓存无效
    
    Args:
        product_id: 产品ID
    """
    # 清除商品详情缓存
    pattern = f"product_detail_{product_id}"
    clear_cache_by_pattern(pattern, 'product_cache')
    
    # 清除可能包含此商品的相关缓存
    product_cache.delete('home_page_hot_products')
    product_cache.delete('home_page_category_products')

def invalidate_category_cache(category_id):
    """
    使特定分类的缓存无效
    
    Args:
        category_id: 分类ID
    """
    # 清除分类页面缓存
    pattern = f"views.decorators.cache.cache_page.*.category_{category_id}"
    clear_cache_by_pattern(pattern, 'default')
    
    # 清除首页分类相关缓存
    default_cache.delete('home_page_categories')
    default_cache.delete('home_page_category_products')

def get_or_set_cache_with_fallback(key, func, timeout=None, cache_alias='default'):
    """
    获取或设置缓存，带有错误回退机制
    
    Args:
        key: 缓存键
        func: 获取数据的函数
        timeout: 缓存超时时间（秒）
        cache_alias: 使用的缓存别名
        
    Returns:
        任意: 缓存的数据或函数的返回值
    """
    selected_cache = caches[cache_alias]
    
    try:
        # 尝试从缓存获取
        result = selected_cache.get(key)
        if result is None:
            # 如果缓存不存在，执行函数并缓存结果
            result = func()
            if result is not None:
                selected_cache.set(key, result, timeout)
        return result
    except Exception as e:
        # 发生错误时，直接执行函数不使用缓存
        print(f"缓存错误: {e}")
        return func()

def rate_limiter(key_prefix, limit=10, period=60, cache_alias='default'):
    """
    简单的请求速率限制器
    
    Args:
        key_prefix: 缓存键前缀
        limit: 在指定时间段内允许的最大请求数
        period: 时间段（秒）
        cache_alias: 使用的缓存别名
        
    Returns:
        tuple: (是否允许请求, 剩余允许的请求数, 重置前的剩余秒数)
    """
    selected_cache = caches[cache_alias]
    current_time = int(time.time())
    
    # 生成请求记录缓存键
    window_key = f"{key_prefix}:{current_time // period}"
    
    # 获取当前窗口的请求计数
    count = selected_cache.get(window_key, 0)
    
    # 如果计数小于限制，增加计数并允许请求
    if count < limit:
        # 为安全起见，先检查键是否存在
        if count == 0:
            selected_cache.set(window_key, 1, period)
        else:
            selected_cache.incr(window_key, 1)
        
        remaining = limit - (count + 1)
        reset_in = period - (current_time % period)
        return True, remaining, reset_in
    
    # 已达到限制，拒绝请求
    reset_in = period - (current_time % period)
    return False, 0, reset_in 